package cn.tedu.csmall.product.service.impl;

import cn.tedu.csmall.product.ex.ServiceCode;
import cn.tedu.csmall.product.ex.ServiceException;
import cn.tedu.csmall.product.mapper.CategoryMapper;
import cn.tedu.csmall.product.pojo.dto.CategoryAddNewDTO;
import cn.tedu.csmall.product.pojo.entity.Category;
import cn.tedu.csmall.product.pojo.vo.CategoryStandardVO;
import cn.tedu.csmall.product.service.ICategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CategoryServiceImpl implements ICategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public void addNew(CategoryAddNewDTO categoryAddNewDTO) {
        log.debug("开始处理【添加品牌】的业务：{}", categoryAddNewDTO);

        // 调用Mapper对象的【根据名称统计数量】方法进行统计
        String name = categoryAddNewDTO.getName();
        int count = categoryMapper.countByName(name);
        log.trace("根据名称【{}】统计数量：{}", name, count);
        // 判断统计结果是否大于0
        if (count > 0) {
            // 是：名称已经被占用，抛出异常（CONFLICT）
            String message = "添加类别失败，尝试添加的类别名称【" + name + "】已经存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        log.trace("品牌名称没有被占用，继续向后执行……");
        // 声明父级类别对象
        CategoryStandardVO parentCategory = null;
        // 声明局部变量depth，默认值为1
        Integer depth = 1;
        // 取出参数中的parentId
        Long parentId = categoryAddNewDTO.getParentId();
        // 判断parentId是否不为0
        if (parentId != 0) {
            log.trace("当前选择了父级类别……");
            // 是：调用Mapper对象的【根据id查询详情】，使用parentId作为参数，执行查询
            parentCategory = categoryMapper.getStandardById(parentId);
            log.trace("从数据库中查询父级类别为：{}", parentCategory);
            // 判断查询结果是否不为null
            if (parentCategory != null) {
                // -- 是：局部变量depth=父级depth+1
                depth += parentCategory.getDepth();
                log.trace("计算得到当前尝试添加的类别的深度：{}", depth);
            } else {
                // -- 否：父级类别不存在，抛出异常（NOT_FOUND）
                String message = "添加类别失败，选定的父级类别不存在！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            }
        }

        // 创建Category实体类的对象
        Category category = new Category();
        // 将参数DTO的各属性值复制到Category实体类对象中
        BeanUtils.copyProperties(categoryAddNewDTO, category);
        // 补全Category实体类对象的属性：depth
        category.setDepth(depth);
        // 补全Category实体类对象的属性：isParent：固定为0
        category.setIsParent(0);
        // 调用Mapper对象的方法，将数据插入到数据库，并获取返回值
        log.debug("准备向数据库中写入类别数据：{}", category);
        int rows = categoryMapper.insert(category);
        // 判断返回值是否不为1
        if (rows != 1) {
            // 是：抛出异常（ERR_INSERT）
            String message = "添加类别失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }

        // 判断parentId是否不为0
        if (parentId != 0) {
            // 是：判断父级类别的isParent是否为0
            if (parentCategory.getIsParent() == 0) {
                log.trace("准备更新父级类别的isParent值……");
                // 是：创建新的Category对象，封装：parentId，isParent(1)
                Category updateParentCategory = new Category();
                //updateParentCategory.setId(parentId);
                updateParentCategory.setIsParent(1);
                // 调用Mapper对象的【更新】方法，执行修改数据，并获取返回值
                int updateRows = categoryMapper.updateById(updateParentCategory);
                // 判断返回值是否不为1
                if (updateRows != 1) {
                    // 是：抛出异常（ERR_UPDATE）
                    String message = "添加类别失败，服务器忙，请稍后再尝试！";
                    log.warn(message);
                    throw new ServiceException(ServiceCode.ERR_UPDATE, message);
                }
                log.trace("更新父级类别的数据完成");
            }
        }
    }

    @Override
    public void deleteById(Long id) {
        // 调用Mapper对象的【根据id查询详情】查询数据，是当前尝试删除的数据
        CategoryStandardVO currentCategory = categoryMapper.getStandardById(id);
        // 判断查询结果是否为null
        if (currentCategory == null) {
            // 是：数据不存在，抛出异常（ERR_NOT_FOUND）
            String message = "删除类别失败，尝试删除的类别不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 检查当前尝试删除的类别是否存在子级类别：判断以上查询结果的isParent是否为1
        if (currentCategory.getIsParent() == 1) {
            // 是：当前尝试删除的类别“是父级类别”（包含子级），抛出异常（ERR_CONFLICT）
            String message = "删除类别失败，尝试删除的类别仍包含子级类别！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        // 调用Mapper对象的【根据id删除】执行删除，并获取返回值
        int rows = categoryMapper.deleteById(id);
        // 判断返回值是否不为1
        if (rows != 1) {
            // 是：抛出异常（ERR_DELETE）
            String message = "删除类别失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }

        // ====== 如果这是父级类别中的最后一个子级，则将父级的isParent改为0 =====
        // 从当前尝试删除的类别对象中取出parentId
        Long parentId = currentCategory.getParentId();
        // 判断当前类别是否不为1级类别，即parentId不为0
        if (parentId != 0) {
            // 调用Mapper对象的countByParentId(parentId)进行统计
            int count = categoryMapper.countByParentId(parentId);
            // 判断统计结果是否为0
            if (count == 0) {
                // 创建新的Category对象，用于更新父级，此Category对象中需要封装：id（parentId），isParent（0）
                Category parentCategory = new Category();
                parentCategory.setId(parentId);
                parentCategory.setIsParent(0);
                // 调用Mapper对象的【更新】功能，执行修改数据，并获取返回值
                rows = categoryMapper.updateById(parentCategory);
                // 判断返回值是否不为1
                if (rows != 1) {
                    // 是：抛出异常（ERR_UPDATE）
                    String message = "删除类别失败，服务器忙，请稍后再尝试！";
                    log.warn(message);
                    throw new ServiceException(ServiceCode.ERR_UPDATE, message);
                }
            }
        }
    }

}
